package nc.bs.gl.report.impl;

import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import com.ufida.report.anareport.base.BaseSearchTemplateCondition;

import nc.bs.dao.BaseDAO;
import nc.bs.gl.report.itf.WageTotalReportService;
import nc.bs.gl.report.tool.VOTransform;
import nc.bs.voucher.report.WageTotalReportVO;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.pub.smart.context.SmartContext;
import nc.pub.smart.data.DataSet;
import nc.pub.smart.metadata.Field;
import nc.pub.smart.metadata.MetaData;
import nc.vo.am.common.util.CollectionUtils;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFLiteralDate;
import nc.vo.pubapp.AppContext;
import nccloud.dto.baseapp.querytree.dataformat.Condition;
import nccloud.dto.baseapp.querytree.dataformat.QueryTreeFormatVO;
import uap.lfw.bq.portal.base.StringUtils;

public class WageTotalReportServiceImpl implements WageTotalReportService {

	String[] fields = new String[] { "wagetype", "businesstotal1", "unittotal1", "total1",
			"businesstotal2", "unittotal2", "total2", "businesstotal3", "unittotal3", "total3",
			"businesstotal4", "unittotal4", "total4", "businesstotal5", "unittotal5", "total5",
			"businesstotal6", "unittotal6", "total6", "businesstotal7", "unittotal7", "total7",
			"businesstotal8", "unittotal8", "total8", "businesstotal9", "unittotal9", "total9",
			"businesstotal10", "unittotal10", "total10", "businesstotal11", "unittotal11", "total11",
			"businesstotal12", "unittotal12", "total12",
			"year", "kjkmcode", "pk_group", "nyearpk"};
	String[] fieldCaptions = new String[] { "费用类别", "业务活动费用", "单位管理费用", "当月小计",
			"业务活动费用", "单位管理费用", "当月小计", "业务活动费用", "单位管理费用", "当月小计",
			"业务活动费用", "单位管理费用", "当月小计","业务活动费用", "单位管理费用", "当月小计",
			"业务活动费用", "单位管理费用", "当月小计","业务活动费用", "单位管理费用", "当月小计",
			"业务活动费用", "单位管理费用", "当月小计","业务活动费用", "单位管理费用", "当月小计",
			"业务活动费用", "单位管理费用", "当月小计","业务活动费用", "单位管理费用", "当月小计",
			"业务活动费用", "单位管理费用", "当月小计",
			"年", "会计科目编码", "集团主键", "年度主键"};
	private static final String pk_group = "0001A210000000000JB9";
	
	// 月份
	String[] periods = {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"};

	@Override
	public DataSet wageTotalDataProcess(SmartContext context) throws BusinessException {
		// 初始化元数据
		MetaData metadata = this.initMetaData();

		// 获取查询条件
		handelContext(context);
		String nyear = ""; // 年度
		String nyearpk = ""; // 年度主键
		if (null != context.getAttribute("nyearpk")) {
			nyearpk = (String) context.getAttribute("nyearpk");
			nyear = getYear(nyearpk);
		} else {
			nyear = getCurrentYear(); // 默认当前年度
		}

		String pkkm = ""; // 会计科目 做成参照，实际查询主键
		if (null != context.getAttribute("pkkm")) {
			pkkm = (String) context.getAttribute("pkkm");
		}

		// 获取人员类型维度凭证数据（借方）
		List<WageTotalReportVO> personTypeData = getPersonTypeData(nyear);
		
		// 获取资金来源维度凭证数据（借方）
		List<WageTotalReportVO> fundSourceData = getFundSourceData(nyear);
		
		// 获取贷方科目维度凭证数据（贷方）
		List<WageTotalReportVO> creditKmData = getCreditKmData(nyear);
		
		// 获取资金来源维度和贷方科目维度差额
		getDifference(fundSourceData, creditKmData, nyear);
		
		// 获取工资总额数字（只有编内和编外，不包括引进生和博士后）
		getWageTota(creditKmData, nyear);

		// 处理数据
		Object[][] result = dataFilter(personTypeData, fundSourceData, creditKmData);

		return new DataSet(metadata, result);
	}

	/**
	 * 	初始化metadata
	 * @return
	 */
	private MetaData initMetaData() {
		Field[] FieldInfo = initField();
		MetaData md = new MetaData();
		for (int i = 0; i < fields.length; i++) {
			md.addField(FieldInfo[i]);
		}
		return md;
	}

	/**
	 * 	初始化返回字段
	 * @return
	 */
	private Field[] initField() {
		Field[] FieldInfo = new Field[fields.length];
		for (int i = 0; i < fields.length; i++) {
			Field filed = new Field();
			filed.setCaption(fieldCaptions[i]);
			filed.setDbColumnType(Types.VARCHAR);
			if (i == 5 || i == 7) { // 5,7对应编制金额，批复金额，金额是否需要调整字段类型，根据情况定
				filed.setDbColumnType(Types.DOUBLE);
			}
			filed.setDbColumnType(Types.VARCHAR);
			filed.setFldname(fields[i]);
			if (i == 2 || i == 6 || i == 8) {// 视情况而定
				filed.setPrecision(500);
			}
			FieldInfo[i] = filed;
		}
		return FieldInfo;
	}

	/**
	 * 	获取当前年
	 * @return
	 */
	public String getCurrentYear() {
		UFDate serverUFDate = AppContext.getInstance().getServerTime().getDate();
		UFLiteralDate serverDate = new UFLiteralDate(serverUFDate.toDate());
		String currentYear = serverDate.getYear() + "";
		return currentYear;
	}

	public void handelContext(SmartContext context) {
		BaseSearchTemplateCondition templateCondition = (BaseSearchTemplateCondition)context.getAttribute("FreeReport_All_Condition");
		if(null != templateCondition) {
			QueryTreeFormatVO conditionTree = templateCondition.getConditionTree();
			List<Condition> list = conditionTree.getQuerycondition().getConditions();
			for(Condition cond : list) {
				String file = cond.getField();
				String val = cond.getValue().getFirstvalue();
				if("between".equals(cond.getOprtype())) {
					val = cond.getValue().getFirstvalue()+","+cond.getValue().getSecondvalue();
				}
				context.setAttribute(file, val);
			}
		}
	}

	/**
	 * 	数据转换
	 * @param values
	 * @return
	 */
	public static String convertToInClause(String value) {
		if(StringUtils.isBlank(value)) {
			return "";
		}
		String[] values = value.split(",");

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < values.length; i++) {
			sb.append('\'').append(values[i]).append('\'');
			if (i < values.length - 1) {
				sb.append(',');
			}
		}
		return sb.toString();
	}
	
	/**
	 * 	获取人员类型维度数据
	 * 	问题：计提专用基金和考核奖 通过摘要获取，绩效工资（取绩效工资中其他绩效）待定,  考核奖怎么取？
	 * 		--业务活动费用5001
	 * 		固定行编内：	50010101基本工资， 50010102津贴补贴， 50010103奖金，考核奖，	5001010701绩效工资（5001010799其他绩效），计提工资总额
	 * 		固定行人员控制总量：	50010101基本工资， 50010102津贴补贴， 50010103奖金，考核奖，5001010701绩效工资（其他绩效）
	 * 		固定行引进生：	50010101基本工资， 50010102津贴补贴， 50010103奖金，考核奖，5001010701绩效工资（其他绩效）
	 *  	固定行市优培生：	50010101基本工资， 50010102津贴补贴， 50010103奖金，考核奖，5001010701绩效工资（其他绩效）
	 *  	固定行编外：	50010101基本工资， 50010102津贴补贴， 50010103奖金，考核奖，5001010701绩效工资（其他绩效），计提工资总额
	 *  	固定行退休：	
	 *  	固定行博士后：	50010101基本工资， 50010102津贴补贴， 50010103奖金，50010107绩效工资
	 *  	--单位活动费用5101
	 *  	固定行编内：		51010101基本工资， 51010102津贴补贴， 	51010103奖金，考核奖，	51010107绩效工资（5101010701），计提工资总额
	 * 		固定行人员控制总量：	51010101基本工资， 51010102津贴补贴， 	51010103奖金，考核奖，	51010107绩效工资（5101010701）
	 * 		固定行引进生：	51010101基本工资， 51010102津贴补贴， 	51010103奖金，考核奖，	51010107绩效工资（5101010701）
	 *  	固定行市优培生：	51010101基本工资， 51010102津贴补贴， 	51010103奖金，考核奖，	51010107绩效工资（5101010701）
	 *  	固定行编外：	51010101基本工资， 51010102津贴补贴， 	51010103奖金，考核奖，	51010107绩效工资（5101010701），计提工资总额
	 *  	固定行退休：	51010399
	 *  	固定行博士后：	51010101基本工资， 51010102津贴补贴， 	51010103奖金，考核奖，	51010107绩效工资（5101010701）
	 * 	报表固定行=============================================================================================================
	 * 	合计（仅包括编内外和引进生，不包括精神文明和综治奖）
	 * 	编内
	 * 	---基本工资
	 * 	---津贴补贴
	 * 	---奖金
	 * 	   考核奖
	 * 	---绩效工资
	 * 	---计提工资总额
	 * 	人员控制总量
	 * 	---基本工资
	 * 	---津贴补贴
	 * 	---奖金
	 * 	   考核奖
	 * 	---绩效工资
	 * 	引进生
	 * 	---基本工资
	 * 	---津贴补贴
	 * 	---奖金
	 * 	   考核奖
	 * 	---绩效工资
	 * 	市优培生
	 * 	---基本工资
	 * 	---津贴补贴
	 * 	---奖金
	 * 	   考核奖
	 * 	---绩效工资
	 * 	编外
	 * 	---基本工资
	 * 	---津贴补贴
	 * 	---奖金
	 * 	   考核奖
	 * 	---绩效工资
	 * 	---计提工资总额
	 * 	退休
	 * 	博士后
	 * 	---基本工资
	 * 	---津贴补贴
	 * 	---奖金
	 * 	---绩效工资
	 * @param year
	 * @return
	 * @throws BusinessException
	 */
	public List<WageTotalReportVO> getPersonTypeData(String year) throws BusinessException {
		List<WageTotalReportVO> result = new ArrayList<>();
		/**
		 * 	STEP 1
		 * 	获取固定行数据
		 */
		// 摘要关键字
//		String[] explanations = {"考核奖", "计提工资总额", "编内", "人员控制总量", "引进生", "市优培生", "编外", "退休", "博士后"};

		// 摘要中有“编内”
		List<Map<String, Object>> bndatas = this.queryPersonTypeData(year, "编内", "");
		// 摘要中有“人员控制总量”
		List<Map<String, Object>> rykzzlbndatas = this.queryPersonTypeData(year, "人员控制总量", "");
		// 摘要中有“引进生”
		List<Map<String, Object>> yjsdatas = this.queryPersonTypeData(year, "引进生", "");
		// 摘要中有“优培生”
		List<Map<String, Object>> sypsdatas = this.queryPersonTypeData(year, "优培生", "");
		// 摘要中有“编外”
		List<Map<String, Object>> bwdatas = this.queryPersonTypeData(year, "编外", "");
		// 摘要中有“退休”
		List<Map<String, Object>> txdatas = this.queryPersonTypeData(year, "退休", "");
		// 摘要中有“博士后”
		List<Map<String, Object>> bshdatas = this.queryPersonTypeData(year, "博士后", "");
		// 摘要中有“考核奖”
//		List<Map<String, Object>> khjdatas = this.queryPersonTypeData(year, personType, "考核奖");
		// 摘要中有“计提工资总额”
//		List<Map<String, Object>> jtgzzedatas = this.queryPersonTypeData(year, personType, "计提工资总额");		
		
		/**
		 * 	STEP 2
		 * 	数据组装固定行
		 */
		// 固定行 
		String[] fixLines = {"人员类型合计",
				"编内","---基本工资","---津贴补贴","---奖金","---考核奖","---绩效工资","---计提工资总额",
				"人员控制总量","---基本工资","---津贴补贴","---奖金","---考核奖","---绩效工资",
				"引进生","---基本工资","---津贴补贴","---奖金","---考核奖","---绩效工资",
				"市优培生","---基本工资","---津贴补贴","---奖金","---考核奖","---绩效工资",
				"编外","---基本工资","---津贴补贴","---奖金","---考核奖","---绩效工资","---计提工资总额",
				"退休",
				"博士后","---基本工资","---津贴补贴","---奖金","---绩效工资", ""};
		for (int i = 0; i < fixLines.length; i++) {
			WageTotalReportVO wage = new WageTotalReportVO();
			wage.setWagetype(fixLines[i]); // 人员类型
			wage.setYear(year); // 年
			wage.setPk_group(pk_group); // 集团主键
			
			List<Map<String, Object>> dealDatas = new ArrayList<>();
			String personType = "";
			int sumIndex = 0; // 人员分类合计标识
			if(i >= 2 && i<= 7) {
				// 处理编内
				dealDatas = bndatas;
				personType = "编内";
				sumIndex = 1;
				if(fixLines[i].contains("考核奖")) {
					// 考核奖
					dealDatas = this.queryPersonTypeData(year, personType, "考核奖");
				}else if(fixLines[i].contains("计提工资总额")) {
					// 计提工资总额
					dealDatas = this.queryPersonTypeData(year, personType, "计提工资总额");
				}
//				else if(fixLines[i].contains("绩效工资")) {
//					// 绩效工资
//					dealDatas = this.queryPersonTypeData(year, personType, "绩效工资");
//				}
			}else if(i >= 9 && i<= 13) {
				// 处理人员控制总量
				dealDatas = rykzzlbndatas;
				personType = "人员控制总量";
				sumIndex = 8;
				if(fixLines[i].contains("考核奖")) {
					// 考核奖
					dealDatas = this.queryPersonTypeData(year, personType, "考核奖");
				}
			}else if(i >= 15 && i<= 19) {
				// 处理引进生
				dealDatas = yjsdatas;
				personType = "引进生";
				sumIndex = 14;
				if(fixLines[i].contains("考核奖")) {
					// 考核奖
					dealDatas = this.queryPersonTypeData(year, personType, "考核奖");
				}
			}else if(i >= 21 && i<= 25) {
				// 处理市优培生
				dealDatas = sypsdatas;
				personType = "市优培生";
				sumIndex = 20;
				if(fixLines[i].contains("考核奖")) {
					// 考核奖
					dealDatas = this.queryPersonTypeData(year, personType, "考核奖");
				}
			}else if(i >= 27 && i<= 32) {
				// 处理编外
				dealDatas = bwdatas;
				personType = "编外";
				sumIndex = 26;
				if(fixLines[i].contains("考核奖")) {
					dealDatas = this.queryPersonTypeData(year, personType, "考核奖");
				}else if(fixLines[i].contains("计提工资总额")) {
					dealDatas = this.queryPersonTypeData(year, personType, "计提工资总额");
				}else if(fixLines[i].contains("基本工资")) {
					dealDatas = this.queryPersonTypeData(year, personType, "基本工资");
				}else if(fixLines[i].contains("津贴补贴")) {
					dealDatas = this.queryPersonTypeData(year, personType, "津贴补贴");
				}else if(fixLines[i].contains("奖金")) {
					dealDatas = this.queryPersonTypeData(year, personType, "奖金");
				}else if(fixLines[i].contains("绩效工资")) {
					dealDatas = this.queryPersonTypeData(year, personType, "绩效工资");
				}
			}else if(i == 33) {
				// 处理退休
				dealDatas = txdatas;
				personType = "退休";
				sumIndex = 33;
			}else if(i >= 35 && i<= 38) {
				// 处理博士后
				dealDatas = bshdatas;
				personType = "博士后";
				sumIndex = 34;
			}
			if(!"".equals(personType) && null !=  dealDatas && StringUtils.isNotBlank(fixLines[i])) {
				for (int j = 0; j < periods.length; j++) {
					wage = this.getVOTransform().dealPersonType(wage, dealDatas, periods[j], fixLines[i], personType);
				}
			}
			result.add(wage);
			// 计算分类合计及合计(从第三行开始计算)
			if(i > 1 && sumIndex != 0 && null !=  dealDatas && !fixLines[i].contains("计提工资总额") ) {
				this.getVOTransform().getSum(result, wage, sumIndex);
			}
		}

		return result;
	}
	
	/**
	 * 	获取资金来源维度凭证数据（借方）
	 * 	问题：其他工资 待确认
	 * 		--业务活动费用
	 * 		固定行1.财政基本拨款经费：	50010101基本工资， 50010102津贴补贴， 50010103奖金+50010107绩效工资，500106其他工资，51010399对个人和家庭的补助费用（退休费）
	 * 		固定行2.财政项目拨款经费：	50010101基本工资， 50010102津贴补贴， 50010103奖金，50010107绩效工资，500106   其他工资（仅含编外+博士后）
	 * 		固定行3.其他经费+科教：		50010101基本工资， 50010102津贴补贴， 50010103奖金，50010107  绩效工资（不包括计提）， 500106 其他工资（编外+博士后），51010399对个人和家庭的补助费用（退休费）
	 *  	--单位活动费用
	 *  	固定行1.财政基本拨款经费：	51010101基本工资， 51010102津贴补贴， 	51010103奖金+51010107绩效工资（5101010701），其他工资，51010399对个人和家庭的补助费用（退休费）
	 * 		固定行2.财政项目拨款经费：	51010101基本工资， 51010102津贴补贴， 	51010103奖金，51010107绩效工资（5101010701），500106   其他工资（仅含编外+博士后）
	 * 		固定行3.其他经费+科教：		51010101基本工资， 51010102津贴补贴， 	51010103奖金， 51010107  绩效工资（不包括计提）（5101010701），500106  其他工资（编外+博士后），51010399对个人和家庭的补助费用（退休费）
	 * 
	 * @param year
	 * @return
	 * @throws BusinessException
	 */
	public List<WageTotalReportVO> getFundSourceData(String year) throws BusinessException {
		List<WageTotalReportVO> result = new ArrayList<>();
		
		// 查询资金来源维度凭证数据（借方）
		List<Map<String, Object>> fundSourceData = queryFundSourceData(year, "", "");
		
		// 组装固定行数据 
		String[] fixLines = {"成本列支工资项目合计",
				"财政基本拨款经费","---基本工资","---津贴补贴","---绩效工资+奖金","---其他工资","---对个人和家庭的补助费用（退休费）",
				"财政项目拨款经费","---基本工资","---津贴补贴","---奖金","---绩效工资","---其他工资（仅含编外+博士后）",
				"其他经费+科教","---基本工资","---津贴补贴","---奖金","---绩效工资（不包括计提）","---其他工资（仅含编外+博士后）","---对个人和家庭的补助费用（退休费）", ""};
		for (int i = 0; i < fixLines.length; i++) {
			WageTotalReportVO wage = new WageTotalReportVO();
			wage.setWagetype(fixLines[i]); // 人员类型
			wage.setYear(year); // 年
			wage.setPk_group(pk_group); // 集团主键
			
			List<Map<String, Object>> dealDatas = fundSourceData;
			String fundSource = "";
			int sumIndex = 0;
			if(i >= 2 && i<= 6) {
				// 处理财政基本拨款经费01
				fundSource = "01"; 
				sumIndex = 1;
				if(fixLines[i].contains("退休")) {
					// 退休
					dealDatas = this.queryFundSourceData(year, fundSource, "退休");
                }
			}else if(i >= 8 && i<= 12) {
				// 处理财政项目拨款经费02
				fundSource = "02";
				sumIndex = 7;
				if(fixLines[i].contains("其他工资")) {
					// 其他工资（仅含编外+博士后）
					dealDatas = this.queryFundSourceData(year, fundSource, "其他工资");
                }
			}else if(i >= 14 && i<= 19) {
				// 处理其他经费+科教03,05
				fundSource = "03,05"; 
				sumIndex = 13;
				if(fixLines[i].contains("绩效工资")) {
					// 绩效工资
					dealDatas = this.queryFundSourceData(year, fundSource, "绩效工资");
                }else if(fixLines[i].contains("其他工资")) {
					// 其他工资（仅含编外+博士后）
					dealDatas = this.queryFundSourceData(year, fundSource, "其他工资");
                }else if(fixLines[i].contains("退休")) {
					// 退休
					dealDatas = this.queryFundSourceData(year, fundSource, "退休");
                }
			}
			if(!"".equals(fundSource) && null !=  dealDatas && StringUtils.isNotBlank(fixLines[i])) {
				for (int j = 0; j < periods.length; j++) {
					wage = this.getVOTransform().dealFundSource(wage, dealDatas, periods[j], fixLines[i], fundSource);
				}
			}
			result.add(wage);
			// 计算分类合计及合计(从第三行开始计算)
			if(i > 1 && sumIndex != 0 && null !=  dealDatas) {
				this.getVOTransform().getSum(result, wage, sumIndex);
			}
			
		}
		return result;
		
	}
	
	/**
	 * 	获取2201科目维度贷方科目
	 * 	问题：	220101基本工资（含离退休费）和不含退休费 待确认
	 * 	应付职工工资-基本工资(不含离退休费) 	220101
	 * 	应付职工工资-国家统一规定津贴补贴		220102
	 * 	应付职工工资-规范津贴补贴（绩效工资-基础性绩效）	22010301
	 * 	应付职工工资-规范津贴补贴（绩效工资-奖励性绩效）	22010302
	 * 	应付职工工资-规范津贴补贴（绩效工资-奖金-当年度）	22010303
	 * 	应付职工工资-管理绩效		22010304
	 * 	应付职工工资-改革性补贴	220104
	 * 	应付职工工资-其他个人收入	220199
	 * 
	 * @param year
	 * @return
	 * @throws BusinessException
	 */
	public List<WageTotalReportVO> getCreditKmData(String year) throws BusinessException {
		List<WageTotalReportVO> result = new ArrayList<>();
		
		// 查询贷方科目维度凭证数据（贷方方）
		List<Map<String, Object>> creditKmData = queryCreditKmData(year);
		
		// 组装固定行数据 
		String[] fixLines = {"挂账合计（贷方）", 
				"应付职工工资-基本工资(不含离退休费) ", 
				"应付职工工资-国家统一规定津贴补贴", 
				"应付职工工资-规范津贴补贴（绩效工资-基础性绩效）",
				"应付职工工资-规范津贴补贴（绩效工资-奖励性绩效）",
				"应付职工工资-规范津贴补贴（绩效工资-奖金-当年度）",
				"应付职工工资-管理绩效","应付职工工资-改革性补贴", 
				"应付职工工资-其他个人收入", ""};
		for (int i = 0; i < fixLines.length; i++) {
			WageTotalReportVO wage = new WageTotalReportVO();
			wage.setWagetype(fixLines[i]); // 人员类型
			wage.setYear(year); // 年
			wage.setPk_group(pk_group); // 集团主键
			
			if(i > 0 && StringUtils.isNotBlank(fixLines[i])) {
				for (int j = 0; j < periods.length; j++) {
					wage = this.getVOTransform().dealCreditKm(wage, creditKmData, periods[j], fixLines[i]);
				}
			}
			result.add(wage);
			// 计算合计(从第二行开始计算)
			this.getVOTransform().getAllSum(result, wage);
			
		}
		return result;
	}
	
	/**
	 * 获取成本列支与挂账是否有差额
	 * @param fundSourceData
	 * @param creditKmData
	 * @param year
	 */
	private void getDifference(List<WageTotalReportVO> fundSourceData, List<WageTotalReportVO> creditKmData, String year) throws BusinessException {
		
		// 组装固定行数据 
		WageTotalReportVO wage = new WageTotalReportVO();
		wage.setWagetype("成本列支与挂账是否有差额"); // 固定行
		wage.setYear(year); // 年
		wage.setPk_group(pk_group); // 集团主键
		// 相减计算差额
		wage = this.getVOTransform().setDifferenceAmount(wage, fundSourceData.get(0), creditKmData.get(0));
		
		creditKmData.add(wage);	
	}
	
	/**
	 * 	获取工资总额数字（只有编内和编外，不包括引进生和博士后）
	 * @param creditKmData
	 * @param year
	 * @throws BusinessException 
	 */
	private void getWageTota(List<WageTotalReportVO> creditKmData, String year) throws BusinessException {
		
		// 查询工资总额数字（只有编内和编外，不包括引进生和博士后）
		List<Map<String, Object>> wageTotaData = queryWageTotaData(year);
		
		// 组装固定行数据 
		WageTotalReportVO wage = new WageTotalReportVO();
		wage.setWagetype("工资总额数字（只有编内和编外，不包括引进生和博士后）"); // 固定行
		wage.setYear(year); // 年
		wage.setPk_group(pk_group); // 集团主键
		
		for (int j = 0; j < periods.length; j++) {
			wage = this.getVOTransform().dealCreditKm(wage, wageTotaData, periods[j], "");
		}
		creditKmData.add(wage);
			
	}
	
	/**
	 * 	查询工资总额数字（只有编内和编外，不包括引进生和博士后）
	 * @param year
	 * @return
	 * @throws BusinessException
	 */
	public List<Map<String, Object>> queryWageTotaData(String year) throws BusinessException {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT gl_detail.periodv period,SUM(gl_detail.debitamount) amount   \n");
		sql.append("  FROM gl_detail \n");
		sql.append(" WHERE gl_detail.dr = 0  \n");
		sql.append("   AND (gl_detail.explanation LIKE '%编外%' OR gl_detail.accountcode LIKE '%编外%') \n");// 过滤摘要
		sql.append("   AND gl_detail.explanation NOT LIKE '%引进生%'  \n");// 过滤摘要
		sql.append("   AND gl_detail.explanation NOT LIKE '%博士后%'  \n");// 过滤摘要
		
		if (StringUtils.isNotBlank(year)) {
			sql.append("   AND gl_detail.yearv = '" + year + "' \n");// 年度
		}
		sql.append(" GROUP BY gl_detail.periodv   \n");

		List<Map<String, Object>> sqlResult = (List<Map<String, Object>>) this.getBaseDAO().executeQuery(sql.toString(),
				new MapListProcessor());
		if (CollectionUtils.isEmpty(sqlResult)) {
			return null;
		}

		return sqlResult;
	}
	
	/**
	 * 	根据贷方科目统计凭证信息
	 * @param year
	 * @return
	 * @throws BusinessException
	 */
	public List<Map<String, Object>> queryCreditKmData(String year) throws BusinessException {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT gl_detail.accountcode kmcode,gl_detail.periodv period,SUM(gl_detail.creditamount) amount   \n");
		sql.append("  FROM gl_detail \n");
		sql.append(" WHERE gl_detail.dr = 0  \n");
		sql.append("   AND gl_detail.accountcode like '2201%'   \n");
		sql.append("   AND gl_detail.explanation NOT LIKE '%补提工资总额%'  \n");
		sql.append("   AND gl_detail.explanation NOT LIKE '%计提工资总额%'  \n");
		
		if (StringUtils.isNotBlank(year)) {
			sql.append("   AND gl_detail.yearv = '" + year + "' \n");// 年度
		}
		
		sql.append(" GROUP BY gl_detail.accountcode,gl_detail.periodv   \n");

		List<Map<String, Object>> sqlResult = (List<Map<String, Object>>) this.getBaseDAO().executeQuery(sql.toString(),
				new MapListProcessor());
		if (CollectionUtils.isEmpty(sqlResult)) {
			return null;
		}

		return sqlResult;
	}
	
	/**
	 * 	根据摘要资金来源和科目统计凭证信息
	 * @param year
	 * @param fundSource
	 * @param keyword
	 * @return
	 * @throws BusinessException
	 */
	public List<Map<String, Object>> queryFundSourceData(String year, String fundSource, String keyword) throws BusinessException {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT gl_detail.accountcode kmcode, gl_detail.periodv period, bd_defdoc.code sourcecode, SUM(gl_detail.debitamount) amount  \n");
		sql.append("  FROM gl_detail \n");
		sql.append(" INNER JOIN gl_docfree1 ON gl_detail.assid = gl_docfree1.assid  \n");
		sql.append("  LEFT JOIN bd_defdoc ON gl_docfree1.f18 = bd_defdoc.pk_defdoc  \n");
		sql.append(" WHERE gl_detail.dr = 0  \n");
		sql.append("   AND gl_docfree1.f18 !='~' AND gl_docfree1.f18 IS NOT NULL  \n");
		sql.append("   AND (gl_detail.accountcode like '5001%' OR gl_detail.accountcode like '5101%')  \n");
		
		if (StringUtils.isNotBlank(year)) {
			sql.append("   AND gl_detail.yearv = '" + year + "' \n");// 年度
		}
		if (StringUtils.isNotBlank(fundSource)) {
			sql.append("   AND bd_defdoc.code IN (" + convertToInClause(fundSource) + ") \n");// 过滤摘要
			if ((fundSource.contains("02") || fundSource.contains("03")) && StringUtils.isNotBlank(keyword) && "其他工资".equals(keyword)) {
				sql.append("   AND  (gl_detail.accountcode like '5001019901%' OR gl_detail.accountcode like '5101019901%') \n");// 过滤摘要 5101019901
				sql.append("   AND gl_detail.explanation NOT LIKE '%计提%'  \n");// 过滤摘要
			}else  if (fundSource.contains("03") && StringUtils.isNotBlank(keyword) && keyword.contains("绩效工资")) {
				sql.append("   AND gl_detail.explanation NOT LIKE '%计提%'  \n");// 过滤摘要
			}else if(StringUtils.isNotBlank(keyword)){
				sql.append("   AND gl_detail.explanation LIKE '%"+ keyword +"%'  \n");// 过滤摘要
			}
		}
		sql.append(" GROUP BY gl_detail.accountcode, gl_detail.periodv, bd_defdoc.code   \n");

		List<Map<String, Object>> sqlResult = (List<Map<String, Object>>) this.getBaseDAO().executeQuery(sql.toString(),
				new MapListProcessor());
		if (CollectionUtils.isEmpty(sqlResult)) {
			return null;
		}

		return sqlResult;
	}
	
	/**
	 * 	根据摘要关键字统计凭证信息
	 * @param year 年
	 * @param personType 人员类型
	 * @param keyword 关键字
	 * @return
	 * @throws BusinessException
	 */
	public List<Map<String, Object>> queryPersonTypeData(String year, String personType, String keyword) throws BusinessException {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT gl_detail.accountcode kmcode,gl_detail.periodv period,SUM(gl_detail.debitamount) amount  \n");
		sql.append("  FROM gl_detail \n");
		sql.append(" WHERE gl_detail.dr = 0  \n");
		sql.append("   AND (gl_detail.accountcode like '5001%' OR gl_detail.accountcode like '5101%')  \n");
		
		if (StringUtils.isNotBlank(year)) {
			sql.append("   AND gl_detail.yearv = '" + year + "' \n");// 年度
		}
		if (StringUtils.isNotBlank(personType) && StringUtils.isNotBlank(keyword) && 
				"编外".equals(personType) && "基本工资".equals(keyword)) {
			sql.append("   AND (gl_detail.accountcode = '50010199010101' OR accountcode = '51010199010101') \n");// 编外基本工资编码
		}else if (StringUtils.isNotBlank(personType) && StringUtils.isNotBlank(keyword) && 
				"编外".equals(personType) && "津贴补贴".equals(keyword)) {
			sql.append("   AND (gl_detail.accountcode = '50010199010102' OR accountcode = '51010199010102') \n");// 编外津贴补贴编码
		}else if (StringUtils.isNotBlank(personType) && StringUtils.isNotBlank(keyword) && 
				"编外".equals(personType) && "奖金".equals(keyword)) {
			sql.append("   AND (gl_detail.accountcode = '5001019901010399' OR accountcode = '5101019901010399') \n");// 编外奖金编码
			sql.append("   AND gl_detail.explanation NOT LIKE '%考核奖%' \n");// 过滤摘要
		}else if (StringUtils.isNotBlank(personType) && StringUtils.isNotBlank(keyword) && 
				"编外".equals(personType) && "绩效工资".equals(keyword)) {
			sql.append("   AND (gl_detail.accountcode like '50010199010106%' OR gl_detail.accountcode like '51010199010106%') \n");// 编外绩效工资编码
		}else if (StringUtils.isNotBlank(personType) && StringUtils.isNotBlank(keyword) && 
				"编内".equals(personType) && "绩效工资".equals(keyword)) {
			sql.append("   AND (gl_detail.accountcode like '50010107%' OR gl_detail.accountcode like '51010107%') \n");// 编外绩效工资编码
		}else if (StringUtils.isNotBlank(personType) && StringUtils.isNotBlank(keyword) && 
				"编外".equals(personType) && "考核奖".equals(keyword)) {
			sql.append("   AND (gl_detail.accountcode = '5001019901010399' OR accountcode = '5101019901010399') \n");// 编外奖金
			sql.append("   AND gl_detail.explanation LIKE '%考核奖%' \n");// 过滤摘要
		}else if (StringUtils.isNotBlank(personType) && StringUtils.isNotBlank(keyword) && 
				"编内".equals(personType) && "计提工资总额".equals(keyword)) {
			sql.append("   AND (gl_detail.explanation LIKE '%补计提%' OR gl_detail.explanation LIKE '%计提工资总额%') \n");// 过滤摘要
		}else {
			if (StringUtils.isNotBlank(personType) && !"计提工资总额".equals(keyword)) {
				sql.append("   AND gl_detail.explanation LIKE '%" + personType + "%' \n");// 过滤摘要
			}
			if (StringUtils.isNotBlank(keyword)) {
				sql.append("   AND gl_detail.explanation LIKE '%" + keyword + "%' \n");// 过滤摘要
			}
			if (!"考核奖".equals(keyword)) {
				sql.append("   AND gl_detail.explanation NOT LIKE '%考核奖%' \n");// 过滤摘要
			}
		}
		if (StringUtils.isNotBlank(keyword) && !"计提工资总额".equals(keyword)) {
			sql.append("   AND gl_detail.explanation NOT LIKE '%计提工资总额%'  \n");
		}
		sql.append(" GROUP BY gl_detail.accountcode,gl_detail.periodv  \n");

		List<Map<String, Object>> sqlResult = (List<Map<String, Object>>) this.getBaseDAO().executeQuery(sql.toString(),
				new MapListProcessor());
		if (CollectionUtils.isEmpty(sqlResult)) {
			return null;
		}

		return sqlResult;
	}

	/**
	 *
	 * 查询预算编制明细数据
	 *
	 * @param nyear         预算年度
	 * @param kmcode        科目
	 * @return
	 * @throws BusinessException
	 */
	public List<Map<String, Object>> queryData(String nyear, String pkkm)
			throws BusinessException {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT nyear, nmonth, pksupplier, suppliercode, suppliername, pkkm, kmcode, kmname, sum(qc) qc, sum(jf) jffs, sum(df) dffs, sum(qc-jf+df) qmye, pk_group  \n");
		sql.append("  FROM ( \n");
		sql.append("SELECT a.yearv nyear, a.periodv nmonth, \n");
		sql.append("       e.pk_supplier pksupplier, e.code suppliercode, e.name suppliername, \n");
		sql.append("       a.pk_accasoa pkkm, g.code kmcode, g.name kmname, \n");
		sql.append("       case when a.periodv='00' then a.creditamount-a.debitamount else 0  end as qc, \n");
		sql.append("       case when a.periodv='00' then 0 else a.debitamount   end as jf, \n");
		sql.append("       case when a.periodv='00' then 0 else a.creditamount end as df, \n");
		sql.append("       a.pk_group pk_group, a.nov as pzbh, a.explanation zy \n");
		sql.append("  FROM gl_detail a  \n");
		sql.append("  LEFT JOIN gl_docfree1 c ON a.assid = c.assid \n");
		sql.append("  LEFT JOIN bd_supplier e ON c.f14 = e.pk_supplier \n");
		sql.append("  LEFT JOIN bd_accasoa f ON a.pk_accasoa = f.pk_accasoa\n");
		sql.append("  LEFT JOIN bd_account g ON f.pk_account = g.pk_account \n");
		sql.append(" WHERE a.dr = 0  \n");
		sql.append("   AND a.pk_org = '0001A210000000003BSQ'  \n");
		sql.append("   AND e.code is not null  \n");
		sql.append("   AND a.pk_systemv<>'PLCF'  \n");
		sql.append("   ) temp  WHERE 1 = 1 \n");

		if (StringUtils.isNotBlank(nyear)) {
			sql.append("   AND temp.nyear = '" + nyear + "' \n");// 年度
		}
		if (StringUtils.isNotBlank(pkkm)) {
			String pkkmString = convertToInClause(pkkm);
			sql.append("   AND temp.pkkm in (" + pkkmString + ") \n");// 科目主键
		}
		sql.append(" group by nyear, nmonth, pksupplier, suppliercode, suppliername, pkkm, kmcode, kmname, pk_group \n");
		sql.append(" ORDER BY nyear DESC, nmonth, kmcode, suppliercode \n");

		List<Map<String, Object>> sqlResult = (List<Map<String, Object>>) this.getBaseDAO().executeQuery(sql.toString(),
				new MapListProcessor());
		if (CollectionUtils.isEmpty(sqlResult)) {
			return null;
		}

		return sqlResult;
	}

	/**
	 * 	根据主键查询年度
	 * @param nyearpk  年度
	 * @return
	 * @throws BusinessException
	 */
	public String getYear(String nyearpk) throws BusinessException {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT periodyear FROM  bd_accperiod  WHERE 1 = 1 \n");
		if (StringUtils.isNotBlank(nyearpk)) {
			sql.append("   AND pk_accperiod = '" + nyearpk + "' \n");// 年度主键
		}

		List<Map<String, Object>> sqlResult = (List<Map<String, Object>>) this.getBaseDAO().executeQuery(sql.toString(),
				new MapListProcessor());
		if (CollectionUtils.isEmpty(sqlResult)) {
			return null;
		}

		return (String) sqlResult.get(0).get("periodyear");
	}

	/**
	 * 	根据主键查询月份
	 * @param nmonthpk         月份
	 * @return
	 * @throws BusinessException
	 */
	public String getMonth(String nmonthpk) throws BusinessException {

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT accperiodmth FROM  bd_accperiodmonth  WHERE 1 = 1 \n");
		if (StringUtils.isNotBlank(nmonthpk)) {
			sql.append("   AND pk_accperiodmonth = '" + nmonthpk + "' \n");// 年度主键
		}

		List<Map<String, Object>> sqlResult = (List<Map<String, Object>>) this.getBaseDAO().executeQuery(sql.toString(),
				new MapListProcessor());
		if (CollectionUtils.isEmpty(sqlResult)) {
			return null;
		}

		return (String) sqlResult.get(0).get("accperiodmth");
	}

	/**
	 * 	过滤数据
	 * @param datas
	 * @return
	 */
	private Object[][] dataFilter(List<WageTotalReportVO> personTypeData, List<WageTotalReportVO> fundSourceData, List<WageTotalReportVO> creditKmData) {
		List<WageTotalReportVO> datas = new ArrayList<>();
		datas.addAll(personTypeData);
		datas.addAll(fundSourceData);
		datas.addAll(creditKmData);
		Collection<Object[]> result = new ArrayList<Object[]>();

		for (int i = 0; i < datas.size(); i++) {
			Object[] rowdata = setDatas(datas.get(i));
			result.add(rowdata);
		}

		return result.toArray(new Object[result.size() == 0 ? 1 : result.size()][]);
	}

	/**
	 * 组装返回数据
	 *
	 * @param data
	 * @return
	 */
	private Object[] setDatas(WageTotalReportVO data) {
		Object[] rowdata = new Object[fields.length];
		rowdata[0] = data.getWagetype();
		rowdata[1] = data.getBusinesstotal1();
		rowdata[2] = data.getUnittotal1();
		rowdata[3] = data.getTotal1();
		rowdata[4] = data.getBusinesstotal2();
		rowdata[5] = data.getUnittotal2();
		rowdata[6] = data.getTotal2();
		rowdata[7] = data.getBusinesstotal3();
		rowdata[8] = data.getUnittotal3();
		rowdata[9] = data.getTotal3();
		rowdata[10] = data.getBusinesstotal4();
		rowdata[11] = data.getUnittotal4();
		rowdata[12] = data.getTotal4();
		rowdata[13] = data.getBusinesstotal5();
		rowdata[14] = data.getUnittotal5();
		rowdata[15] = data.getTotal5();
		rowdata[16] = data.getBusinesstotal6();
		rowdata[17] = data.getUnittotal6();
		rowdata[18] = data.getTotal6();
		rowdata[19] = data.getBusinesstotal7();
		rowdata[20] = data.getUnittotal7();
		rowdata[21] = data.getTotal7();
		rowdata[22] = data.getBusinesstotal8();
		rowdata[23] = data.getUnittotal8();
		rowdata[24] = data.getTotal8();
		rowdata[25] = data.getBusinesstotal9();
		rowdata[26] = data.getUnittotal9();
		rowdata[27] = data.getTotal9();
		rowdata[28] = data.getBusinesstotal10();
		rowdata[29] = data.getUnittotal10();
		rowdata[30] = data.getTotal10();
		rowdata[31] = data.getBusinesstotal11();
		rowdata[32] = data.getUnittotal11();
		rowdata[33] = data.getTotal11();
		rowdata[34] = data.getBusinesstotal12();
		rowdata[35] = data.getUnittotal12();
		rowdata[36] = data.getTotal12();
		rowdata[37] = data.getYear();
		rowdata[38] = data.getKjkmcode();
		rowdata[39] = data.getPk_group();
		rowdata[40] = data.getNyearpk();
		return rowdata;
	}

	private BaseDAO baseDAO;

	public BaseDAO getBaseDAO() {
		return baseDAO == null ? new BaseDAO() : baseDAO;
	}
	
	/**
	 * VO数据转换
	 */
	private VOTransform voTransform = null;
	
	private VOTransform getVOTransform()
	{
		if (voTransform == null)
		{
			voTransform = new VOTransform();
		}
		return voTransform;
	}

}
